package pessoal.funcionario;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import pessoal.Endereco;
import pessoal.Pessoa;
import pessoal.RepositorioPessoaBDR;
import pessoal.cliente.RepositorioClientesBDR;
import pessoal.funcionario.exception.FuncionarioExistenteException;
import pessoal.funcionario.exception.FuncionarioInvalidoException;
import util.CampoObrigatorioException;
import util.Conexao;
import util.ErroAcessoRepositorioException;

public class RepositorioFuncionariosBDR extends RepositorioPessoaBDR implements
	IRepositorioFuncionarios {

    private static final String UPDATE_FUNCIONARIO = "UPDATE func SET salario = ? "
	    + " WHERE cpf_func = ?";

    private static final String INSERT_FUNCIONARIO = "INSERT INTO func (cpf_func,salario) "
	    + "VALUES (?,?)";

    private static final String CONSULTA_FUNCIONARIO = "SELECT * FROM pessoa INNER "
	    + "JOIN func ON cpf = cpf_func WHERE cpf_func = ?";

    private static final String DELETE_FUNCIONARIO = "DELETE FROM func WHERE cpf_func = ?";

    private static final String CONSULTA_FUNCIONARIO_LISTAR = "SELECT * FROM pessoa INNER "
	    + "JOIN func ON cpf = cpf_func";

    private static final String CONSULTA_FUNCIONARIO_EXISTE = "SELECT * FROM func "
	    + "WHERE cpf_func = ?";

    public void atualizarFuncionario(Funcionario func)
	    throws FuncionarioInvalidoException, ErroAcessoRepositorioException {
	Connection con = Conexao.getConexao();
	PreparedStatement pstmt = null;
	try {
	    pstmt = con.prepareStatement(UPDATE_FUNCIONARIO);
	    pstmt.setDouble(1, func.getSalario());
	    pstmt.setString(2, func.getCpf());
	    int rows = pstmt.executeUpdate();
	    if (rows <= 0) {
		throw new FuncionarioInvalidoException(func.getCpf());
	    }
	    Endereco end = new Endereco(func.getEndereco().getRua(), func
		    .getEndereco().getNumero(), func.getEndereco()
		    .getComplemento(), func.getEndereco().getBairro(), func
		    .getEndereco().getCidade(), func.getEndereco().getCep(),
		    func.getEndereco().getUf());

	    Pessoa pessoa = new Pessoa(func.getNome(), func.getRg(), func
		    .getCpf(), end);
	    super.alterarPessoa(pessoa);
	} catch (SQLException e) {
	    throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD, e, e
		    .getErrorCode());
	} finally {
	    Conexao.fechaRecursos(con, pstmt, null);
	}

    }

    public Funcionario consultarFuncionario(String cpf)
	    throws FuncionarioInvalidoException, ErroAcessoRepositorioException {
	Funcionario func = null;
	Connection con = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	con = Conexao.getConexao();
	try {
	    pstmt = con.prepareStatement(CONSULTA_FUNCIONARIO);
	    pstmt.setString(1, cpf);
	    rs = pstmt.executeQuery();
	    if (rs.next()) {
		String nome = rs.getString("nome");
		String rg = rs.getString("rg");
		double salario = rs.getDouble("salario");
		String rua = rs.getString("rua");
		String numero = rs.getString("numero");
		String complemento = rs.getString("complemento");
		String bairro = rs.getString("bairro");
		String cidade = rs.getString("cidade");
		String cep = rs.getString("cep");
		String uf = rs.getString("uf");
		func = new Funcionario(cpf, nome, rg, new Endereco(rua, numero,
			complemento, bairro, cidade, cep, uf), salario);
	    } else {
		throw new FuncionarioInvalidoException(cpf);
	    }
	} catch (SQLException e) {
	    throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD, e, e
		    .getErrorCode());
	} finally {
	    Conexao.fechaRecursos(con, pstmt, rs);
	}
	return func;
    }

    /*
     * O excluir exclui de funcionario mas nao exclui de pessoa caso esse
     * funcionario tb seja um cliente. se esse funcionario nao for tb cliente
     * ele exclui das duas.
     * 
     */
    public void excluirFuncionario(String cpf)
	    throws FuncionarioInvalidoException, ErroAcessoRepositorioException {
	PreparedStatement pstmt = null;
	Connection con = null;
	if (existeFuncionario(cpf)) {
	    try {
		con = Conexao.getConexao();
		pstmt = con.prepareStatement(DELETE_FUNCIONARIO);
		pstmt.setString(1, cpf);
		pstmt.executeUpdate();
		RepositorioClientesBDR repClientes = new RepositorioClientesBDR();
		if (!repClientes.existeCliente(cpf)) {
		    super.excluirPessoa(cpf);
		}
	    } catch (SQLException e) {
		throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD, e,
			e.getErrorCode());
	    } finally {
		Conexao.fechaRecursos(con, pstmt, null);
	    }
	} else {
	    throw new FuncionarioInvalidoException(cpf);
	}

    }

    public boolean existeFuncionario(String cpf)
	    throws ErroAcessoRepositorioException {
	Connection con = null;
	PreparedStatement pstmt = null;
	con = Conexao.getConexao();
	ResultSet rs = null;
	try {
	    pstmt = con.prepareStatement(CONSULTA_FUNCIONARIO_EXISTE);
	    pstmt.setString(1, cpf);
	    rs = pstmt.executeQuery();
	    if (rs.next()) {
		String qtdLinhas = rs.getString("cpf_func");
		return (qtdLinhas != null);
	    }
	} catch (SQLException e) {
	    throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD, e, e
		    .getErrorCode());
	} finally {
	    Conexao.fechaRecursos(con, pstmt, rs);
	}

	return false;
    }

    /*
     * Insere em pessoa e depois insere em funcionario
     * 
     */
    public void inserirFuncionario(Funcionario func)
	    throws FuncionarioExistenteException,
	    ErroAcessoRepositorioException, CampoObrigatorioException {
	Endereco end = new Endereco(func.getEndereco().getRua(), func
		.getEndereco().getNumero(),
		func.getEndereco().getComplemento(), func.getEndereco()
			.getBairro(), func.getEndereco().getCidade(), func
			.getEndereco().getCep(), func.getEndereco().getUf());

	Pessoa pessoa = new Pessoa(func.getNome(), func.getRg(), func.getCpf(),
		end);
	if (func.getCpf() != null && func.getCpf() != ""
		&& func.getNome() != null && func.getNome() != ""
		&& func.getRg() != null && func.getRg() != "") {
	    Connection con = null;
	    PreparedStatement pstmt = null;
	    try {
		super.inserePessoa(pessoa);
		if (!existeFuncionario(func.getCpf())) {
		    con = Conexao.getConexao();
		    pstmt = con.prepareStatement(INSERT_FUNCIONARIO);
		    pstmt.setString(1, func.getCpf());
		    pstmt.setDouble(2, func.getSalario());
		    pstmt.executeUpdate();
		} else {
		    throw new FuncionarioExistenteException(func.getCpf());
		}
	    } catch (SQLException e) {
		throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD, e,
			e.getErrorCode());
	    } finally {
		Conexao.fechaRecursos(con, pstmt, null);
	    }
	} else {
	    throw new CampoObrigatorioException("CPF, Nome e RG.");
	}
    }

    public List<Funcionario> listarFuncionarios()
	    throws ErroAcessoRepositorioException {
	PreparedStatement pstmt = null;
	Connection con = null;
	ResultSet rs = null;
	ArrayList<Funcionario> funcionarios = new ArrayList<Funcionario>();
	con = Conexao.getConexao();
	try {
	    pstmt = con.prepareStatement(CONSULTA_FUNCIONARIO_LISTAR);
	    rs = pstmt.executeQuery();
	    while (rs.next()) {
		String cpf = rs.getString("cpf");
		String nome = rs.getString("nome");
		String rg = rs.getString("rg");
		double salario = rs.getDouble("salario");
		String rua = rs.getString("rua");
		String numero = rs.getString("numero");
		String complemento = rs.getString("complemento");
		String bairro = rs.getString("bairro");
		String cidade = rs.getString("cidade");
		String cep = rs.getString("cep");
		String uf = rs.getString("uf");
		Endereco end = new Endereco(rua, numero, complemento, bairro,
			cidade, cep, uf);
		Funcionario func = new Funcionario(cpf, nome, rg, end, salario);
		funcionarios.add(func);
	    }
	} catch (SQLException e) {
	    throw new ErroAcessoRepositorioException(MSG_ERRO_ACESSO_BD, e, e
		    .getErrorCode());
	} finally {
	    Conexao.fechaRecursos(con, pstmt, rs);
	}
	return funcionarios;
    }

}
